home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\NAMES.C < prev    next >
C/C++ Source or Header  |  1995-01-04  |  19KB  |  977 lines

  1. /*
  2.  * names.c: This here is used to maintain a list of all the people currently
  3.  * on your channel.  Seems to work 
  4.  *
  5.  *
  6.  * Written By Michael Sandrof
  7.  *
  8.  * Copyright(c) 1990 
  9.  *
  10.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  11.  */
  12.  
  13. #ifndef lint
  14. static    char    rcsid[] = "@(#)$Id: names.c,v 1.16 1994/09/03 14:23:07 mrg Stab $";
  15. #endif
  16.  
  17. #include "irc.h"
  18.  
  19. #include "ircaux.h"
  20. #include "names.h"
  21. #include "window.h"
  22. #include "screen.h"
  23. #include "server.h"
  24. #include "lastlog.h"
  25. #include "list.h"
  26. #include "output.h"
  27.  
  28. static    char    mode_str[] = "iklmnpst";
  29.  
  30. static    void    add_to_mode_list __P((char *, char *));
  31. static    void    check_mode_list_join __P((char *));
  32.  
  33. /* NickList is declared in window.h */
  34.  
  35. /* ChannelList - moved to names.h */
  36.  
  37. struct modelist
  38. {
  39.     char    *chan;
  40.     char    *mode;
  41.     struct modelist *next;
  42. }    *mode_list = (struct modelist *) 0;
  43.  
  44. /* channel_list: list of all the channels you are currently on */
  45. static    ChannelList *channel_list = (ChannelList *) 0;
  46.  
  47. /* clear_channel: erases all entries in a nick list for the given channel */
  48. static    void
  49. clear_channel(chan)
  50.     ChannelList *chan;
  51. {
  52.     NickList *tmp,
  53.         *next;
  54.  
  55.     for (tmp = chan->nicks; tmp; tmp = next)
  56.     {
  57.         next = tmp->next;
  58.         new_free(&(tmp->nick));
  59.         new_free(&tmp);
  60.     }
  61.     chan->nicks = NULL;
  62. }
  63.  
  64. extern    ChannelList *
  65. lookup_channel(channel, server, unlink)
  66.     char    *channel;
  67.     int    server;
  68.     int    unlink;
  69. {
  70.     ChannelList    *chan = channel_list,
  71.             *last = NULL;
  72.  
  73.     if (server == -1)
  74.         server = primary_server;
  75.     while(chan)
  76.     {
  77.         if((chan->server == server) && !my_stricmp(chan->channel, channel))
  78.         {
  79.             if (unlink)
  80.             {
  81.                 if (last)
  82.                     last->next = chan->next;
  83.                 else
  84.                     channel_list = chan->next;
  85.             }
  86.             break;
  87.         }
  88.         last = chan;
  89.         chan = chan->next;
  90.     }
  91.     return(chan);
  92. }
  93.  
  94. /*
  95.  * add_channel: adds the named channel to the channel list.  If the channel
  96.  * is already in the list, nothing happens.   The added channel becomes the
  97.  * current channel as well 
  98.  */
  99. void
  100. add_channel(channel, server)
  101.     char    *channel;
  102.     int    server;
  103. {
  104.     ChannelList *new;
  105.     TravInfo ti;
  106.  
  107.     if ((new = lookup_channel(channel, server, 0)) != NULL)
  108.     {
  109.         new->mode = 0;
  110.         new->s_mode = (char *) 0;
  111.         new->limit = 0;
  112.         new->chop = 0;
  113.         new->server = server;
  114.         new->window = curr_scr_win;
  115.         new->key = NULL;
  116.         malloc_strcpy(&(new->channel), channel);
  117.         clear_channel(new);
  118.     }
  119.     else
  120.     {
  121.         new = (ChannelList *) new_malloc(sizeof(ChannelList));
  122.         new->channel = (char *) 0;
  123.         new->mode = 0;
  124.         new->s_mode = (char *) 0;
  125.         new->limit = 0;
  126.         new->chop = 0;
  127.         new->server = server;
  128.         new->window = curr_scr_win;
  129.         new->key = NULL;
  130.         malloc_strcpy(&(new->channel), channel);
  131.         new->nicks = NULL;
  132.         add_to_list(&channel_list, new);
  133.     }
  134.     if (!is_current_channel(channel, 0))
  135.     {
  136.         int    flag = 1;
  137.         Window    *tmp;
  138.  
  139.         while ((tmp = traverse_all_windows(&flag, &ti)) != NULL)
  140.         {
  141.             if (!tmp->waiting_channel)
  142.                 continue;
  143.             if (!my_stricmp(tmp->waiting_channel, channel))
  144.             {    
  145.                 set_channel_by_refnum(tmp->refnum, channel);
  146.                 new->window = tmp;
  147.                 new_free(&tmp->waiting_channel);
  148.                 update_all_windows();
  149.                 return;
  150.             }
  151.         }
  152.         set_channel_by_refnum(0, channel);
  153.         new->window = curr_scr_win;
  154.     }
  155.     update_all_windows();
  156. }
  157.  
  158. /*
  159.  * add_to_channel: adds the given nickname to the given channel.  If the
  160.  * nickname is already on the channel, nothing happens.  If the channel is
  161.  * not on the channel list, nothing happens (although perhaps the channel
  162.  * should be addded to the list?  but this should never happen) 
  163.  */
  164. void
  165. add_to_channel(channel, nick, server)
  166.     char    *channel;
  167.     char    *nick;
  168.     int    server;
  169. {
  170.     NickList *new;
  171.     ChannelList *chan;
  172.     int    ischop = 0;
  173.  
  174.     if ((chan = lookup_channel(channel, server, 0)) != NULL)
  175.     {
  176.         if (*nick == '@')
  177.         {
  178.             nick++;
  179.             if (my_stricmp(nick, get_server_nickname(server)) == 0)
  180.             {
  181.                 check_mode_list_join(channel);
  182.                 chan->chop = 1;
  183.             }
  184.             ischop = 1;
  185.         }
  186.         else if (*nick == '+')
  187.         {
  188.             nick++;
  189.  
  190.             if (*nick == '@')
  191.             {
  192.                 nick++;
  193.                 if (my_stricmp(nick, get_server_nickname(server)) == 0)
  194.                 {
  195.                     check_mode_list_join(channel);
  196.                     chan->chop = 1;
  197.                 }
  198.                 ischop = 1;
  199.             }
  200.         }
  201.  
  202.         if ((new = (NickList *) remove_from_list(&(chan->nicks), nick))
  203.                 != NULL)
  204.         {
  205.             new_free(&(new->nick));
  206.             new_free(&new);
  207.         }
  208.         new = (NickList *) new_malloc(sizeof(NickList));
  209.         new->nick = (char *) 0;
  210.         new->chanop = ischop;
  211.         malloc_strcpy(&(new->nick), nick);
  212.         add_to_list(&(chan->nicks), new);
  213.     }
  214. }
  215.  
  216.  
  217. /*
  218.  * recreate_mode: converts the bitmap representation of a channels mode into
  219.  * a string 
  220.  *
  221.  * This malloces what it returns, but nothing that calls this function
  222.  * is expecting to have to free anything.  Therefore, this function
  223.  * should not malloc what it returns.  (hop)
  224.  *
  225.  * but this leads to horrible race conditions, so we add a bit to
  226.  * the channel structure, and cache the string value of mode, and
  227.  * the u_long value of the cached string, so that each channel only
  228.  * has one copy of the string.  -mrg, june '94.
  229.  */
  230. static    char    *
  231. recreate_mode(chan)
  232.     ChannelList *chan;
  233. {
  234.     int    mode_pos = 0,
  235.         str_pos = 0,
  236.         mode;
  237.     static    char    str[20];
  238.  
  239.     /* first check if cached string value is ok */
  240.  
  241.     if (chan->mode == chan->i_mode)
  242.         return (chan->s_mode);
  243.  
  244.     chan->i_mode = chan->mode;
  245.     buffer[0] = '\0';
  246.     mode = chan->mode;
  247.     while (mode)
  248.     {
  249.         if (mode % 2)
  250.             buffer[str_pos++] = mode_str[mode_pos];
  251.         mode /= 2;
  252.         mode_pos++;
  253.     }
  254.     buffer[str_pos] = '\0';
  255.     if (chan->key)
  256.     {
  257.         strcat(buffer, " ");
  258.         strcat(buffer, chan->key);
  259.     }
  260.     if (chan->limit)
  261.     {
  262.         sprintf(str, " %d", chan->limit);
  263.         strcat(buffer, str);
  264.     }
  265.     malloc_strcpy(&chan->s_mode, buffer);
  266.     return (chan->s_mode);
  267. }
  268.  
  269. /*
  270.  * decifer_mode: This will figure out the mode string as returned by mode
  271.  * commands and convert that mode string into a one byte bit map of modes 
  272.  */
  273. static    int
  274. decifer_mode(mode_str, mode, chop, nicks, key)
  275.     char    *mode_str;
  276.     u_long    *mode;
  277.     char    *chop;
  278.     NickList **nicks;
  279.     char    **key;
  280. {
  281.     char    *limit = 0;
  282.     char    *person;
  283.     int    add = 0;
  284.     int    limit_set = 0;
  285.     int    limit_reset = 0;
  286.     char    *rest,
  287.         *the_key;
  288.     NickList *ThisNick;
  289.     unsigned char    value = 0;
  290.  
  291.     if (!(mode_str = next_arg(mode_str, &rest)))
  292.         return -1;
  293.     for (; *mode_str; mode_str++)
  294.     {
  295.         switch (*mode_str)
  296.         {
  297.         case '+':
  298.             add = 1;
  299.             value = 0;
  300.             break;
  301.         case '-':
  302.             add = 0;
  303.             value = 0;
  304.             break;
  305.         case 'p':
  306.             value = MODE_PRIVATE;
  307.             break;
  308.         case 'l':
  309.             value = MODE_LIMIT;
  310.             if (add)
  311.             {
  312.                 limit_set = 1;
  313.                 if (!(limit = next_arg(rest, &rest)))
  314.                     limit = empty_string;
  315.                 else if (0 == strncmp(limit, "0", 1))
  316.                     limit_reset = 1, limit_set = 0, add = 0;
  317.             }
  318.             else
  319.                 limit_reset = 1;
  320.             break;
  321.         case 't':
  322.             value = MODE_TOPIC;
  323.             break;
  324.         case 'i':
  325.             value = MODE_INVITE;
  326.             break;
  327.         case 'n':
  328.             value = MODE_MSGS;
  329.             break;
  330.         case 's':
  331.             value = MODE_SECRET;
  332.             break;
  333.         case 'm':
  334.             value = MODE_MODERATED;
  335.             break;
  336.         case 'o':
  337.             if ((person = next_arg(rest, &rest)) &&
  338.                 !my_stricmp(person, get_server_nickname(from_server)))
  339.                 *chop = add;
  340.             ThisNick = (NickList *) list_lookup(nicks, person,
  341.                     !USE_WILDCARDS, !REMOVE_FROM_LIST);
  342.             if (ThisNick)
  343.                 ThisNick->chanop=add;
  344.             break;
  345.         case 'k':
  346.             value = MODE_KEY;
  347.             the_key = next_arg(rest, &rest);
  348.             if (add)
  349.                 malloc_strcpy(key, the_key);
  350.             else
  351.                 new_free(key);
  352.             break;    
  353.         case 'v':
  354.         case 'b':
  355.             (void) next_arg(rest, &rest);
  356.             break;
  357.         }
  358.         if (add)
  359.             *mode |= value;
  360.         else
  361.             *mode &= ~value;
  362.     }
  363.     if (limit_set)
  364.         return (atoi(limit));
  365.     else if (limit_reset)
  366.         return(0);
  367.     else
  368.         return(-1);
  369. }
  370.  
  371. /*
  372.  * get_channel_mode: returns the current mode string for the given channel
  373.  */
  374. char    *
  375. get_channel_mode(channel, server)
  376.     char    *channel;
  377.     int    server;
  378. {
  379.     ChannelList *tmp;
  380.  
  381.     if ((tmp = lookup_channel(channel, server, 0)) != NULL)
  382.         return (recreate_mode(tmp));
  383.     return (empty_string);
  384. }
  385.  
  386. /*
  387.  * set_channel_mode: This will set the mode of the given channel.  It will
  388.  * zap any existing mode and replace it with the mode given 
  389.  */
  390. void
  391. set_channel_mode(channel, mode)
  392.     char    *channel,
  393.         *mode;
  394. {
  395.     ChannelList *tmp;
  396.     int    limit;
  397.  
  398.     if ((tmp = lookup_channel(channel, from_server, 0)) != NULL)
  399.     {
  400.         tmp->mode = 0;
  401.         if ((limit = decifer_mode(mode, &(tmp->mode), &(tmp->chop),
  402.             &(tmp->nicks), &(tmp->key))) != -1)
  403.             tmp->limit = limit;
  404.     }
  405. }
  406.  
  407. /*
  408.  * update_channel_mode: This will modify the mode for the given channel
  409.  * according the the new mode given.  
  410.  */
  411. void
  412. update_channel_mode(channel, mode)
  413.     char    *channel,
  414.         *mode;
  415. {
  416.     ChannelList *tmp;
  417.     int    limit;
  418.  
  419.     if ((tmp = lookup_channel(channel, from_server, 0)) != NULL)
  420.     {
  421.         if ((limit = decifer_mode(mode, &(tmp->mode), &(tmp->chop),
  422.                 &(tmp->nicks), &(tmp->key))) != -1)
  423.             tmp->limit = limit;
  424.     }
  425. }
  426.  
  427. /*
  428.  * is_channel_mode: returns the logical AND of the given mode with the
  429.  * channels mode.  Useful for testing a channels mode 
  430.  */
  431. int
  432. is_channel_mode(channel, mode)
  433.     char    *channel;
  434.     int    mode;
  435. {
  436.     ChannelList *tmp;
  437.  
  438.     if ((tmp = lookup_channel(channel, from_server, 0)) != NULL)
  439.         return (tmp->mode & mode);
  440.     return 0;
  441. }
  442.  
  443. /*
  444.  * remove_channel: removes the named channel from the channel_list.  If the
  445.  * channel is not on the channel_list, nothing happens.  If the channel was
  446.  * the current channel, this will select the top of the channel_list to be
  447.  * the current_channel, or 0 if the list is empty. 
  448.  */
  449. void
  450. remove_channel(channel, server)
  451.     char    *channel;
  452.     int    server;
  453. {
  454.     ChannelList *tmp;
  455.  
  456.     if (channel)
  457.     {
  458.         if ((tmp = lookup_channel(channel, server, 1)) != NULL)
  459.         {
  460.             clear_channel(tmp);
  461.             new_free(&(tmp->channel));
  462.             new_free(&(tmp->key));
  463.             new_free(&tmp);
  464.         }
  465.         if (is_current_channel(channel, 1))
  466.             switch_channels();
  467.     }
  468.     else
  469.     {
  470.         ChannelList *next;
  471.  
  472.         for (tmp = channel_list; tmp; tmp = next)
  473.         {
  474.             next = tmp->next;
  475.             clear_channel(tmp);
  476.             new_free(&(tmp->channel));
  477.             new_free(&(tmp->key));
  478.             new_free(&tmp);
  479.         }
  480.         channel_list = (ChannelList *) 0;
  481.     }
  482.     update_all_windows();
  483. }
  484.  
  485. /*
  486.  * remove_from_channel: removes the given nickname from the given channel. If
  487.  * the nickname is not on the channel or the channel doesn't exist, nothing
  488.  * happens. 
  489.  */
  490. void
  491. remove_from_channel(channel, nick, server)
  492.     char    *channel;
  493.     char    *nick;
  494.     int    server;
  495. {
  496.     ChannelList *chan;
  497.     NickList *tmp;
  498.  
  499.     if (channel)
  500.     {
  501.         if ((chan = lookup_channel(channel, server, 0)) != NULL)
  502.         {
  503.             if ((tmp = (NickList *) list_lookup(&(chan->nicks),
  504.                nick, !USE_WILDCARDS, REMOVE_FROM_LIST)) != NULL)
  505.             {
  506.                 new_free(&(tmp->nick));
  507.                 new_free(&tmp);
  508.             }
  509.         }
  510.     }
  511.     else
  512.     {
  513.         for (chan = channel_list; chan; chan = chan->next)
  514.         {
  515.             if (chan->server == server)
  516.             {
  517.                 if ((tmp = (NickList *)
  518.                     list_lookup(&(chan->nicks), nick,
  519.                     !USE_WILDCARDS, REMOVE_FROM_LIST)) != NULL)
  520.                 {
  521.                     new_free(&(tmp->nick));
  522.                     new_free(&tmp);
  523.                 }
  524.             }
  525.         }
  526.     }
  527. }
  528.  
  529. /*
  530.  * rename_nick: in response to a changed nickname, this looks up the given
  531.  * nickname on all you channels and changes it the new_nick 
  532.  */
  533. void
  534. rename_nick(old_nick, new_nick, server)
  535.     char    *old_nick,
  536.         *new_nick;
  537.     int    server;
  538. {
  539.     ChannelList *chan;
  540.     NickList *tmp;
  541.  
  542.     for (chan = channel_list; chan; chan = chan->next)
  543.     {
  544.         if ((chan->server == server) != 0)
  545.         {
  546.             if ((tmp = (NickList *) list_lookup(&chan->nicks, old_nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)) != NULL)
  547.             {
  548.                 new_free(&tmp->nick);
  549.                 malloc_strcpy(&tmp->nick, new_nick);
  550.             }
  551.         }
  552.     }
  553. }
  554.  
  555. /*
  556.  * is_on_channel: returns true if the given nickname is in the given channel,
  557.  * false otherwise.  Also returns false if the given channel is not on the
  558.  * channel list. 
  559.  */
  560. int
  561. is_on_channel(channel, nick)
  562.     char    *channel;
  563.     char    *nick;
  564. {
  565.     ChannelList *chan;
  566.  
  567.     chan = lookup_channel(channel, from_server, 0);
  568.     if (chan)
  569.     {
  570.         if (list_lookup(&(chan->nicks), nick, !USE_WILDCARDS,
  571.                 !REMOVE_FROM_LIST))
  572.             return (1);
  573.     }
  574.     return (0);
  575. }
  576.  
  577. int
  578. is_chanop(channel, nick)
  579.     char    *channel;
  580.     char    *nick;
  581. {
  582.     ChannelList *chan;
  583.     NickList *Nick;
  584.  
  585.     if ((chan = lookup_channel(channel, from_server, 0)) &&
  586.             (Nick = (NickList *) list_lookup(&(chan->nicks),
  587.             nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)) &&
  588.             Nick->chanop)
  589.         return (1);
  590.     return (0);
  591. }
  592.  
  593. void
  594. show_channel(chan)
  595.     ChannelList *chan;
  596. {
  597.     NickList *tmp;
  598.     int    buffer_len,
  599.         len;
  600.     char    *nicks = NULL;
  601.     char    *s;
  602.  
  603.     *buffer = (char) 0;
  604.     buffer_len = 0;
  605.     s = recreate_mode(chan);
  606.     for (tmp = chan->nicks; tmp; tmp = tmp->next)
  607.     {
  608.         len = strlen(tmp->nick);
  609.         if (buffer_len + len >= (BIG_BUFFER_SIZE / 2))
  610.         {
  611.             malloc_strcpy(&nicks, buffer);
  612.             say("\t%s +%s (%s): %s", chan->channel, s, get_server_name(chan->server), nicks);
  613.             *buffer = (char) 0;
  614.             buffer_len = 0;
  615.         }
  616.         strmcat(buffer, tmp->nick, BIG_BUFFER_SIZE);
  617.         strmcat(buffer, " ", BIG_BUFFER_SIZE);
  618.         buffer_len += len + 1;
  619.     }
  620.     malloc_strcpy(&nicks, buffer);
  621.     say("\t%s +%s (%s): %s", chan->channel, s, get_server_name(chan->server), nicks);
  622.     new_free(&nicks);
  623. }
  624.  
  625. /* list_channels: displays your current channel and your channel list */
  626. void
  627. list_channels()
  628. {
  629.     ChannelList *tmp;
  630.  
  631.     if (channel_list)
  632.     {
  633.         if (get_channel_by_refnum(0))
  634.             say("Current channel %s", get_channel_by_refnum(0));
  635.         else
  636.             say("No current channel for this window");
  637.         say("You are on the following channels:");
  638.         for (tmp = channel_list; tmp; tmp = tmp->next)
  639.         {
  640.             if (tmp->server == from_server)
  641.                 show_channel(tmp);
  642.         }
  643.         if (connected_to_server != 1)
  644.         {
  645.             say("Other servers:");
  646.             for (tmp = channel_list; tmp; tmp = tmp->next)
  647.             {
  648.                 if (tmp->server != from_server)
  649.                     show_channel(tmp);
  650.             }
  651.         }
  652.     }
  653.     else
  654.         say("You are not on any channels");
  655. }
  656.  
  657. void
  658. switch_channels()
  659. {
  660.     ChannelList *tmp;
  661.  
  662.     if (channel_list)
  663.     {
  664.         if (get_channel_by_refnum(0))
  665.         {
  666.             if ((tmp = lookup_channel(get_channel_by_refnum(0),
  667.                 from_server, 0)) != NULL)
  668.             {
  669.                 for (tmp = tmp->next; tmp; tmp = tmp->next)
  670.                 {
  671.                     if ((tmp->server == from_server) &&
  672.                         !is_current_channel(tmp->channel,
  673.                         0))
  674.                     {
  675.                         set_channel_by_refnum(0,
  676.                             tmp->channel);
  677.                         update_all_windows();
  678.                         return;
  679.                     }
  680.                 }
  681.             }
  682.         }
  683.         for (tmp = channel_list; tmp; tmp = tmp->next)
  684.         {
  685.             if ((tmp->server == from_server) &&
  686.                 (!is_current_channel(tmp->channel, 0)))
  687.             {
  688.                 set_channel_by_refnum(0, tmp->channel);
  689.                 update_all_windows();
  690.                 return;
  691.             }
  692.         }
  693.     }
  694. }
  695.  
  696. /* real_channel: returns your "real" channel (your non-multiple channel) */
  697. char    *
  698. real_channel()
  699. {
  700.     ChannelList *tmp;
  701.  
  702.     if (channel_list)
  703.     {
  704.         for (tmp = channel_list; tmp; tmp = tmp->next)
  705.         {
  706.             if ((tmp->server == from_server) &&
  707.                     (*(tmp->channel) != '#'))
  708.                 return (tmp->channel);
  709.         }
  710.     }
  711.     return ((char *) 0);
  712. }
  713.  
  714. int
  715. get_channel_server(channel)
  716.     char    *channel;
  717. {
  718.     ChannelList *chan;
  719.  
  720.     if ((chan = (ChannelList *) list_lookup(&channel_list, channel,
  721.             !USE_WILDCARDS, !REMOVE_FROM_LIST)) != NULL)
  722.         return(chan->server);
  723.     return(-1);
  724. }
  725.  
  726. void
  727. change_server_channels(old, new)
  728.     int    old,
  729.         new;
  730. {
  731.     ChannelList *tmp;
  732.  
  733.     for(tmp = channel_list; tmp ;tmp = tmp->next)
  734.     {
  735.         if (tmp->server == old)
  736.             tmp->server = new;
  737.     }
  738. }
  739.  
  740. void
  741. clear_channel_list(server)
  742.     int    server;
  743. {
  744.     ChannelList *tmp;
  745.  
  746.     tmp = channel_list;
  747.     while(tmp)
  748.     {
  749.         if (tmp->server == server)
  750.         {
  751.             remove_channel(tmp->channel, server);
  752.             tmp = channel_list;
  753.         }
  754.         else
  755.             tmp = tmp->next;
  756.     }
  757. }
  758.  
  759. /*
  760.  * reconnect_all_channels: used after you get disconnected from a server, 
  761.  * clear each channel nickname list and re-JOINs each channel in the 
  762.  * channel_list ..  
  763.  */
  764. void
  765. reconnect_all_channels()
  766. {
  767.     ChannelList *tmp;
  768.     int    version;
  769.     char    *s;
  770.  
  771.     for (tmp = channel_list; tmp; tmp = tmp->next)
  772.     {
  773.         if (tmp->server == from_server)
  774.         {
  775.             s = recreate_mode(tmp);
  776.             if (tmp->window->current_channel)
  777.                 malloc_strcpy(&tmp->window->waiting_channel,
  778.                     tmp->window->current_channel);
  779.             if (get_server_version(from_server) >= Server2_8)
  780.             {
  781.                 send_to_server("JOIN %s%s%s", tmp->channel, tmp->key ? " " : "", tmp->key ? tmp->key : "");
  782.                 if ((char *) 0 != s)
  783.                     add_to_mode_list(tmp->channel, s);
  784.             }
  785.             else
  786.                 send_to_server("JOIN %s%s%s", tmp->channel, version ? " " : "", version ? s : "");
  787.             clear_channel(tmp);
  788.         }
  789.     }
  790.     clear_channel_list(from_server);
  791.     message_from((char *) 0, LOG_CRAP);
  792. }
  793.  
  794. extern    char    *
  795. channel_key(channel)
  796.     char    *channel;
  797. {
  798.     ChannelList *tmp;
  799.  
  800.     for (tmp = channel_list; tmp && strcmp(tmp->channel, channel); tmp = tmp->next)
  801.         ;
  802.     return tmp ? tmp->key : empty_string;
  803. }
  804.  
  805. char    *
  806. what_channel(nick)
  807.     char    *nick;
  808. {
  809.     ChannelList *tmp;
  810.  
  811.     if (curr_scr_win->current_channel &&
  812.         is_on_channel(curr_scr_win->current_channel, nick))
  813.         return curr_scr_win->current_channel;
  814.     for (tmp = channel_list; tmp; tmp = tmp->next)
  815.     {
  816.         if ((tmp->server == from_server) && (list_lookup(&(tmp->nicks),
  817.             nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)))
  818.             return tmp->channel;
  819.     }
  820.     return NULL;
  821. }
  822.  
  823. char    *
  824. walk_channels(nick, init)
  825.     int    init;
  826.     char    *nick;
  827. {
  828.     static    ChannelList *tmp = (ChannelList *) 0;
  829.  
  830.     if (init)
  831.         tmp = channel_list;
  832.     else if (tmp)
  833.         tmp = tmp->next;
  834.     for (;tmp ; tmp = tmp->next)
  835.         if ((tmp->server == from_server) && (list_lookup(&(tmp->nicks),
  836.                 nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)))
  837.             return (tmp->channel);
  838.     return (char *) 0;
  839. }
  840.  
  841. int
  842. get_channel_oper(channel, server)
  843.     char    *channel;
  844.     int    server;
  845. {
  846.     ChannelList *chan;
  847.  
  848.     if ((chan = lookup_channel(channel, server, 0)) != NULL)
  849.         return chan->chop;
  850.     else
  851.         return 1;
  852. }
  853.  
  854. extern    void
  855. set_channel_window(window, channel)
  856.     Window    *window;
  857.     char    *channel;
  858. {
  859.     ChannelList    *tmp;
  860.  
  861.     if (!channel)
  862.         return;
  863.     for (tmp = channel_list; tmp; tmp = tmp->next)
  864.         if (!my_stricmp(channel, tmp->channel) &&
  865.                 from_server == tmp->server)
  866.         {
  867.             tmp->window = window;
  868.             return;
  869.         }
  870. }
  871.  
  872. extern    char    *
  873. create_channel_list(window)
  874.     Window    *window;
  875. {
  876.     ChannelList    *tmp;
  877.     char    *value = (char *) 0;
  878.  
  879.     *buffer = '\0';
  880.     for (tmp = channel_list; tmp; tmp = tmp->next)
  881.         if (tmp->server == window->server)
  882.         {
  883.             strcat(buffer, tmp->channel);
  884.             strcat(buffer, " ");
  885.         }
  886.     malloc_strcpy(&value, buffer);
  887.  
  888.     return value;
  889. }
  890.  
  891. extern    void
  892. channel_server_delete(i)
  893.     int    i;
  894. {
  895.     ChannelList    *tmp;
  896.  
  897.     for (tmp = channel_list ; tmp; tmp = tmp->next)
  898.         if (tmp->server >= i)
  899.             tmp->server--;
  900. }
  901.  
  902. extern    void
  903. set_waiting_channel(i)
  904.     int    i;
  905. {
  906.     Window    *tmp;
  907.     int    flag = 1;
  908.     TravInfo ti;
  909.  
  910.     while ((Window *) 0 != (tmp = traverse_all_windows(&flag, &ti)))
  911.         if (tmp->server == i && tmp->current_channel)
  912.         {
  913.             tmp->waiting_channel = tmp->current_channel;
  914.             tmp->current_channel = (char *) 0;
  915.         }
  916. }
  917.  
  918. static    void
  919. add_to_mode_list(channel, mode)
  920.     char    *channel;
  921.     char    *mode;
  922. {
  923.     struct modelist    *mptr;
  924.  
  925.     if (!channel || !*channel || !mode || !*mode)
  926.         return;
  927.     mptr = (struct modelist *) new_malloc(sizeof(struct modelist));
  928.     mptr->chan = (char *) 0;
  929.     mptr->mode = (char *) 0;
  930.     mptr->next = mode_list;
  931.     mode_list = mptr;
  932.     malloc_strcpy(&mptr->chan, channel);
  933.     malloc_strcpy(&mptr->mode, mode);
  934. }
  935.  
  936. static    void
  937. check_mode_list_join(channel)
  938.     char    *channel;
  939. {
  940.     struct modelist *mptr = mode_list;
  941.  
  942.     for (;(struct modelist *) 0 != mptr; mptr = mptr->next)
  943.     {
  944.         if (0 == my_stricmp(mptr->chan, channel))
  945.         {
  946.             send_to_server("MODE %s %s", mptr->chan, mptr->mode);
  947.             return;
  948.         }
  949.     }
  950.     remove_from_mode_list(channel);
  951. }
  952.  
  953. extern    void
  954. remove_from_mode_list(channel)
  955.     char    *channel;
  956. {
  957.     struct modelist *curr, *prev, *next;
  958.  
  959.     for (curr = mode_list; curr; curr = next)
  960.     {
  961.         next = curr->next;
  962.         if (0 == my_stricmp(curr->chan, channel))
  963.         {
  964.             if (curr == mode_list)
  965.                 mode_list = curr->next;
  966.             else
  967.                 prev->next = curr->next;
  968.             prev = curr;
  969.             new_free(&curr->chan);
  970.             new_free(&curr->mode);
  971.             new_free(&curr);
  972.         }
  973.         else
  974.             prev = curr;
  975.     }
  976. }
  977.